using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using HengTong.Model.Db.SupplyChain.Material;
using HengTong.ViewModel.SupplyChain.SysMaterialVms;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using UUIDNext;
using WalkingTec.Mvvm.Core;

namespace HengTong.ViewModel.SupplyChain.SysMaterialSkuVms;

public partial class SysMaterialSkuVm
{
    /// <summary>
    /// 查询或创建SKU
    /// </summary>
    /// <param name="request"></param>
    public async Task GetOrCreateAsync(GetOrCreateSkuRequest request)
    {
        var material = await DC.Set<SysMaterial>()
            .Include(e => e.Attributes)
            .ThenInclude(e => e.Values)
            .Include(e => e.Skus)
            .ThenInclude(e => e.Attributes)
            .FirstOrDefaultAsync(e => e.ID == request.MaterialId);
        if (material == null)
        {
            MSD.AddModelError(nameof(request.MaterialId), "指定的物料不存在");
            return;
        }
        var sku = material.Skus.FirstOrDefault(sku =>
            sku.Attributes.Count == request.AttributeValueIds.Length &&
            sku.Attributes.All(attr => Array.Exists(request.AttributeValueIds, id => id == attr.ValueId))
        );
        if (sku == null)
        {
            var attributes = material.Attributes.Where(e => e.IsKeyAttribute).OrderBy(e => e.Order).ToList();
            sku = new SysMaterialSku
            {
                ID = Uuid.NewDatabaseFriendly(Database.SqlServer),
                MaterialId = request.MaterialId,
                Attributes = new List<SysMaterialSkuAttributes>(),
                Code = await this.GenerateCodeAsync(request.MaterialId)
            };
            foreach (var attribute in attributes)
            {
                var value = attribute.Values.FirstOrDefault(e => request.AttributeValueIds.Contains(e.ID));
                if (value == null)
                {
                    MSD.AddModelError(" ", $"缺少【{attribute.Name}】属性, 请选择完整的关键属性值");
                    return;
                }
                var element = new SysMaterialSkuAttributes();
                element.SkuId = sku.ID;
                element.ValueId = value.ID;
                element.Value = value;
                sku.Attributes.Add(element);
            }
            sku.Name = string.Join("/", sku.Attributes.OrderBy(a => a.Value.Attribute.Order).Select(a => a.Value.Value));
            await DC.Set<SysMaterialSku>().AddAsync(sku);
            await DC.SaveChangesAsync();
        }
        Entity = sku;
    }
    
    private static readonly SemaphoreSlim Slim = new(1, 1);
    
    /// <summary>
    /// 生成SKU编码, 必须提供物料ID
    /// </summary>
    /// <returns></returns>
    public async Task<string> GenerateCodeAsync(Guid materialId)
    {
        await Slim.WaitAsync();
        try
        {
            var material = await DC.Set<SysMaterial>()
                .FirstOrDefaultAsync(e => e.ID == materialId);
            if (material == null)
            {
                throw new Exception($"物料不存在，无法生成SKU编码，物料ID: {materialId}");
            }
            material.SerialNumber++;
            var code = $"{material.Code}-{material.SerialNumber.ToString().PadLeft(4, '0')}";
            await DC.SaveChangesAsync();
            return code;
        }
        finally
        {
            Slim.Release();
        }
    }
}


public class GetOrCreateSkuRequest
{
    [Required]
    public Guid MaterialId { get; set; }
    
    [Required]
    public Guid[] AttributeValueIds { get; set; }
}